#include "config.h"

#include "libms2sim.h"

#ifdef _WIN32

#include <math.h>

double log1p(double x)
{
	return log(1 + x);
}
#endif

const char *
msl_get_duration_str(ecm_uint32 duration)
{
	static char	buf[256];
	ecm_uint32	hour, min, sec;

	sec = duration % 60;
	duration /= 60;
	min = duration % 60;
	duration /= 60;
	hour = duration;

	if (hour < 10)
		ecm_snprintf(buf, 256, "%02u:%02u:%02u", hour, min, sec);
	else
		ecm_snprintf(buf, 256, "%u:%02u:%02u", hour, min, sec);
	return buf;
}

const char *
msl_get_bandwidth_str(ecm_double bandwidth)
{
	static char	buf[64];
	ecm_uint32	unit = 0;
	const char	*unitstr[] = { "B", "KiB", "MiB", "GiB" };

	while (unit < 4 && bandwidth > 1024) {
		bandwidth /= 1024;
		unit++;
	}
	ecm_snprintf(buf, 64, "%.2lf%s/sec", bandwidth, unitstr[unit]);

	return buf;
}

const char *
msl_get_capacity_str(ecm_double capacity)
{
	static char	buf[64];
	ecm_uint32	unit = 0;
	const char	*unitstr[] = { "B", "KiB", "MiB", "GiB" };

	while (unit < 4 && capacity > 1024) {
		capacity /= 1024;
		unit++;
	}
	if (unit == 0 || capacity == (ecm_uint32)capacity)
		ecm_snprintf(buf, 64, "%u%s", (ecm_uint32)capacity, unitstr[unit]);
	else
		ecm_snprintf(buf, 64, "%.2lf%s", capacity, unitstr[unit]);

	return buf;
}

ecm_uint32
msl_parse_duration(char *str)
{
	char	*ptr;
	char	*tok;
	ecm_uint32	hour, min, sec;
	ecm_uint32	secs = 0;

	if ((tok = ecm_strtok(str, ":", &ptr)) == NULL)
		return 0;
	if (ecm_sscanf(tok, "%u", &hour) != 1)
		return 0;
	secs = hour * 3600;
	if ((tok = ecm_strtok(NULL, ":", &ptr)) != NULL) {
		if (ecm_sscanf(tok, "%u", &min) != 1)
			return 0;
		secs += (min * 60);

		if ((tok = ecm_strtok(NULL, ":", &ptr)) != NULL) {
			if (ecm_sscanf(tok, "%u", &sec) != 1)
				return 0;
			secs += sec;
		}
	}

	return secs;
}

ECMBOOL
msl_parse_arrival_rate(char *str, ecm_double *parrival_rate)
{
	char	*slash;
	ecm_uint32	unit = 1;

	if ((slash = ecm_strchr(str, '/'))) {
		*slash = '\0';
		switch (slash[1]) {
		case 's':
			break;
		case 'm':
			unit = 60;
			break;
		case 'h':
			unit = 3600;
			break;
		default:
			return ECM_FALSE;
		}
	}
	if (ecm_sscanf(str, "%lf", parrival_rate) != 1)
		return ECM_FALSE;

	*parrival_rate = *parrival_rate / unit;

	return ECM_TRUE;
}

ECMBOOL
msl_parse_bandwidth(char *str, ecm_uint64 *pBW)
{
	ecm_uint32	unit = 1;
	ecm_double	BW;
	char	*p;

	for (p = str; *p; p++) {
		switch (*p) {
		case 'G':
		case 'M':
		case 'K':
			if (p[1] != 'i' || p[2] != 'B' || p[3] != '\0')
				return ECM_FALSE;
			if (*p == 'G')
				unit = 1024 * 1024 * 1024;
			else if (*p == 'M')
				unit = 1024 * 1024;
			else
				unit = 1024;
			*p = '\0';
			goto out;
		case 'B':
			if (p[1] != '\0')
				return ECM_FALSE;
		default:
			break;
		}
	}

out:
	if (ecm_sscanf(str, "%lf", &BW) != 1 || BW < 0)
		return ECM_FALSE;

	*pBW = (ecm_uint64)(BW * unit);

	return ECM_TRUE;
}
